#include "Render/PiccoloTexture.h"

#include "PiccoloApplication.h"
#include "Render/PiccoloRenderContext.h"
#include "Graphics/PiccoloVKDevice.h"
#include "Graphics/PiccoloVKImage.h"
#include "Graphics/PiccoloVKImageView.h"
#include "Graphics/PiccoloVKBuffer.h"

#define STB_IMAGE_IMPLEMENTATION

#include "stb/stb_image.h"

namespace Piccolo
{
    PiccoloTexture::PiccoloTexture(const std::string &filePath)
    {
        int channel;
        uint8_t* data = stbi_load(filePath.c_str(), reinterpret_cast<int *>(&mWidth), reinterpret_cast<int *>(&mHeight), &channel, STBI_rgb_alpha);
        if (!data)
        {
            LOG_E("Can not load this image: {0}", filePath);
            return;
        }

        mFormat = VK_FORMAT_R8G8B8A8_UNORM;
        size_t size = sizeof(uint8_t) * mWidth * mHeight * 4;
        CreateImage(size, data);

        stbi_image_free(data);
    }

    PiccoloTexture::PiccoloTexture(uint32_t width, uint32_t height, RGBAColor *pixels) : mWidth(width), mHeight(height)
    {
        mFormat = VK_FORMAT_R8G8B8A8_UNORM;
        size_t size = sizeof(uint8_t) * mWidth * mHeight * 4;
        CreateImage(size, pixels);
    }

    PiccoloTexture::~PiccoloTexture()
    {
        mImageView.reset();
        mImage.reset();
    }

    void PiccoloTexture::CreateImage(size_t size, void *data)
    {
        PiccoloRenderContext* renderContext = PiccoloApplication::GetAppContext()->renderContext;
        PiccoloVKDevice* device = renderContext->GetDevice();
        mImage = std::make_shared<PiccoloVKImage>(device, VkExtent3D{ mWidth, mHeight, 1 }, mFormat, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_SAMPLE_COUNT_1_BIT);
        mImageView = std::make_shared<PiccoloVKImageView>(device, mImage->GetImage(), mFormat, VK_IMAGE_ASPECT_COLOR_BIT);

        // 数据拷贝到buffer
        std::shared_ptr<PiccoloVKBuffer> stageBuffer = std::make_shared<PiccoloVKBuffer>(device, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, size, data, true);

        // buffer拷贝到image
        VkCommandBuffer cmdBuffer = device->CreateAndBeginSingleCommandBuffer();

        // UNDEFINED -> TRANSFER_DST
        PiccoloVKImage::TransitionLayout(cmdBuffer, mImage->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
        // 从buffer的内容复制到image中
        mImage->CopyFromBuffer(cmdBuffer, stageBuffer.get());
        // TRANSFER_DST -> SHADER_READ_ONLY
        PiccoloVKImage::TransitionLayout(cmdBuffer, mImage->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);

        device->EndSingleCommandBuffer(cmdBuffer);

        stageBuffer.reset();
    }
}
